package net.boyandi.picback;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.ListSelectionModel;
import javax.swing.SpringLayout;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.table.TableColumnModel;

import org.apache.log4j.Logger;

import at.fhj.utils.misc.FileUtils;
import at.fhj.utils.swing.FancyTable;
import at.fhj.utils.swing.TableSorter;

import com.thoughtworks.xstream.XStream;

/**
 * @author Ilya Boyandin
 */
public class PicBack extends JFrame {

    public static final String VERSION = "0.1";
    public static final ImageIcon DIRECTORY_ICON = new ImageIcon(PicBack.class.getResource("res/Directory.gif"));;
    public static final ImageIcon START_SCAN_ICON = new ImageIcon(PicBack.class.getResource("res/Rescan.gif"));;
    public static final ImageIcon BACKUP_ICON = new ImageIcon(PicBack.class.getResource("res/Start16.gif"));;

    private static final long serialVersionUID = -8273209782702071700L;
    private static final String SETTINGS_FILE_NAME = ".picback";

    private static final Logger logger = Logger.getLogger(PicBack.class.getName());

    private XStream xstream;
    private Settings settings;
    private String appStartDir;
    private final JMenuBar menubar;

    private Action showSettingsAction;
    private final JPanel toolBarPanel;
    private final JToolBar actionsToolBar;
    private final FancyTable scannedFoldersTable;

    private ScanFoldersAction scanFoldersAction;
    private BackupAction backupAction;
    private final ScannedFoldersTableModel scannedFoldersTableModel;
    private AboutAction showAboutAction;

    public PicBack() {
        super("Picback");

        initActions();
        
        toolBarPanel = new JPanel(new BorderLayout());
//        toolBarPanel.setLayout(new BoxLayout(toolBarPanel, BoxLayout.X_AXIS));
        add(toolBarPanel, BorderLayout.NORTH);

        actionsToolBar = buildActionsToolBar();
        toolBarPanel.add(actionsToolBar);

        menubar = buildMenuBar();
        setJMenuBar(menubar);
        
        SpringLayout layout = new SpringLayout();
        JPanel tablePanel = new JPanel(layout);

        scannedFoldersTableModel = new ScannedFoldersTableModel();
        TableSorter sorter = new TableSorter(scannedFoldersTableModel);
        sorter.setSortingStatus(2, TableSorter.DESCENDING);
//        sorter.setColumnSortable(tableModel.getColumnCount() - 1, false);
        
        scannedFoldersTable = new FancyTable(sorter);
        sorter.setTableHeader(scannedFoldersTable.getTableHeader());
        TableColumnModel tcm = scannedFoldersTable.getColumnModel();
        tcm.getColumn(0).setPreferredWidth(180);
        tcm.getColumn(1).setPreferredWidth(10);
        tcm.getColumn(2).setPreferredWidth(10);
        tcm.getColumn(3).setPreferredWidth(10);
        tcm.getColumn(4).setPreferredWidth(270);


        scannedFoldersTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
        scannedFoldersTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        scannedFoldersTable.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        tablePanel.add(scannedFoldersTable);

        JScrollPane scrollPane = new JScrollPane(scannedFoldersTable);
//        scrollPane.setPreferredSize(new Dimension(400, 300));

        layout.putConstraint(SpringLayout.NORTH, scrollPane, 10, SpringLayout.NORTH, tablePanel);
        layout.putConstraint(SpringLayout.WEST, scrollPane, 10, SpringLayout.WEST, tablePanel);
        layout.putConstraint(SpringLayout.EAST, tablePanel, 10, SpringLayout.EAST, scrollPane);
        layout.putConstraint(SpringLayout.SOUTH, tablePanel, 10, SpringLayout.SOUTH, scrollPane);

        
        add(scrollPane);


        setPreferredSize(new Dimension(900, 600));
        pack();

        final Dimension size = getSize();
        final Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
        final int locX = (screen.width - size.width) / 2;
        final int locY = (screen.height - size.height) / 2;
        setLocation(locX, locY);

        
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                exit();
            }
        });
    }

    private JToolBar buildActionsToolBar() {
        JToolBar tb = new JToolBar();
        tb.putClientProperty("JToolBar.isRollover", Boolean.TRUE);
        tb.setFloatable(false);
        tb.add(scanFoldersAction);
        tb.add(backupAction);
        tb.addSeparator();
        return tb;
    }

    public void setFolderScanResults(List<FolderScanResult> results) {
        scannedFoldersTableModel.setFolderScanResults(results);
        scannedFoldersTableModel.fireTableDataChanged();
    }
    
    public List<FolderScanResult> getSelectedFolders() {
        int[] selRows = scannedFoldersTable.getSelectedRows();
        List<FolderScanResult> selResults = new ArrayList<FolderScanResult>();
        for (int index : selRows) {
            
            selResults.add((FolderScanResult) scannedFoldersTable.getValueAt(index, -1));
        }
        return selResults;
    }

    public Settings getSettings() {
        return settings;
    }

    public void setSettings(Settings settings) {
        this.settings = settings;
    }

    private void initActions() {
        showSettingsAction = new AbstractAction() {
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) {
                new SettingsDialog(PicBack.this).setVisible(true);
            }
        };
        scanFoldersAction = new ScanFoldersAction(this);
        backupAction = new BackupAction(this);
        showAboutAction = new AboutAction(this);
    }

    private JMenuBar buildMenuBar() {
        final JMenuBar mb = new JMenuBar();
        JMenu menu;
        JMenuItem item;

        menu = new JMenu("File");
        mb.add(menu);


//        menu = new JMenu("Window");
//        mb.add(menu);


//        menu.addSeparator();

        item = new JMenuItem("Settings...");
        item.addActionListener(showSettingsAction);
        menu.add(item);

        item = new JMenuItem("Exit");
        item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                exit();
            }
        });
        menu.add(item);

        menu = new JMenu("Help");
        mb.add(menu);

        item = new JMenuItem(showAboutAction);
        menu.add(item);
        
        return mb;
    }

    public String getAppStartDir() {
        return appStartDir;
    }

    public void setAppStartDir(String appStartDir) {
        this.appStartDir = appStartDir;
    }

    public void startup() {
        setAppStartDir(System.getProperty("user.dir"));
        loadSettings();
        setVisible(true);
        
        List<String> foldersToScan = getSettings().getFoldersToScan();
        if (foldersToScan.size() > 0) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    scannedFoldersTable.requestFocus();
                    scanFoldersAction.startScanning();
                } 
            });
        }
    }

    public void shutdown() {
        saveSettings();
        logger.info("Exiting application");
        System.exit(0);
    }

    protected void loadSettings() {
        Settings prefs = null;
        final String fileName = getSettingsFileName();
        if (new File(fileName).isFile()) {
            logger.info("Loading settings from " + fileName);
            try {
                prefs = (Settings) getXStream().fromXML(new InputStreamReader(new FileInputStream(fileName), "utf-8"));
            } catch (Throwable th) {
                logger.error("Loading settings failed", th);
            }
        }
        if (prefs == null) {
            prefs = new Settings();
        }
        this.settings = prefs;
    }

    protected void saveSettings() {
        final String fileName = getSettingsFileName();
        logger.info("Saving settings to " + fileName);
        try {
            getXStream().toXML(settings, new OutputStreamWriter(new FileOutputStream(fileName), "utf-8"));
        } catch (Throwable th) {
            logger.error("Loading settings failed", th);
        }
    }

    protected String getSettingsFileName() {
        return getAppStartDir() + File.separator + SETTINGS_FILE_NAME;
    }

    public XStream getXStream() {
        if (xstream == null) {
            xstream = new XStream();
            xstream.alias("picback-settings", Settings.class);
        }
        return xstream;
    }

    public boolean confirmExit() {
        int confirm = JOptionPane.showConfirmDialog(this,
                "Are you sure you want to exit application?", "Exit",
                JOptionPane.YES_NO_OPTION);
        if (confirm == JOptionPane.YES_OPTION) {
            return true;
        } else {
            return false;
        }
    }

    private void exit() {
//        if (confirmExit()) {
            dispose();
            shutdown();
//        }
    }
    
    private final FileFilter FILES_TO_BACKUP_FILTER = new FileFilter() {
        public boolean accept(File f) {
            return f.isFile()  &&
                   getSettings().isFiletypeToScan(FileUtils.getExtension(f.getName()));
        }
    };

    public FileFilter getFilesToBackupFilter() {
        return FILES_TO_BACKUP_FILTER;
    }

    public static void main(String[] args) {
        initLF();
        new PicBack().startup();
    }
    
    private static void initLF() {
//        final String lafName;
//
//        lafName = "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel";
//
//        try {
//            UIManager.setLookAndFeel(lafName);
//        } catch (Exception e) {
//            logger.error("Can't set look & feel:" + e);
//        }

        UIManager.put("TableHeader.font", new Font(Font.DIALOG, Font.BOLD, 11));
    }

}
